import React, { useEffect, useState, useSyncExternalStore, } from 'react'
import ReactReduxContext from '../ReactReduxContext'
function useSelector(selector) {
  const { store } = React.useContext(ReactReduxContext) // 获取上下文对象中的值
  // 返回一个组件需要状态
  const selectedField = useSyncExternalStore2(
    store.subscribe, // 获取需要执行的订阅函数
    () => selector(store.getState()), // 快照 获取仓库中的分状态
  )
  return selectedField
}

/**
 * 根据快照的变化来执行订阅函数
 * @param {*} subscribe 需要执行的订阅函数
 * @param {*} getSnapShot 快照
 */
function useSyncExternalStore2(subscribe, getSnapShot) {
  let [ state, setState ] = useState(getSnapShot()) // 定义一个状态
  useEffect(() => { // 副作用
    // 保存订阅函数 当仓库中的状态发生变化后执行订阅函数
    const unsubscribe = subscribe(() => {
      setState(getSnapShot()) // 执行 getSnapShot 函数将更新的快照作为参数传递 来修改组件的状态触发更新
    })
    // 当组件卸载的时候 执行清理清理函数
    return unsubscribe
  }, [])
  return state
}

export default useSelector


/**
 * useSyncExternalStore 实现思想
 * 1. 接收一个 subscribe 保存订阅函数的函数
 * 2. 接收一个 getSnapShot 获取快照的函数
 * 3. 内部使用 useState 来创建一个组件的状态
 * 4. 在 useEffect 中定义副作用
 *     1. 调用 subscribe 函数时传递一个订阅函数 内部保存订阅函数 ( 当仓库中的状态发生变化后自动执行订阅函数 )
 *     2. 在订阅函数内部调用 setState 函数时传递 getSnapShot() 最新的快照值 修改组件的状态触发组件更新
 */
